﻿using Microsoft.Kinect;
using Microsoft.Kinect.Toolkit;
using Microsoft.Kinect.Toolkit.Controls;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;

namespace ProjetoKinect.Model
{
    public class KinectController
    {
        public KinectSensorChooser sensorChooser;
        private KinectRegion kinectRegion;
        public KinectSensor sensor;

        public KinectController(KinectRegion kinectRegion) {
            this.kinectRegion = kinectRegion;
        }

        public KinectController()
        {
            this.sensorChooser = new KinectSensorChooser();
            this.sensorChooser.KinectChanged += SensorChooserOnKinectChanged;
            this.sensorChooser.Start();
            
        }

        public void setKinectSensor()
        {
            this.sensorChooser = new KinectSensorChooser();
            this.sensorChooser.KinectChanged += SensorChooserOnKinectChanged;
            this.sensorChooser.Start();
            var regionSensorBinding = new Binding("Kinect") { Source = this.sensorChooser };
            BindingOperations.SetBinding(this.kinectRegion, KinectRegion.KinectSensorProperty, regionSensorBinding);
        }
        public void startSensor()
        {
            this.sensorChooser.Start();
        }

        public void stopFullSensor()
        {
            sensorChooser.Stop();
            if (null == sensor)
            {
                return;
            }

            // Stop streaming
            sensor.Stop();

            if (null != sensor.AudioSource)
            {
                sensor.AudioSource.Stop();
            }

            if (null != sensor.SkeletonStream)
            {
                sensor.SkeletonStream.Disable();
            }

            if (null != sensor.DepthStream)
            {
                sensor.DepthStream.Disable();
            }

            if (null != sensor.ColorStream)
            {
                sensor.ColorStream.Disable();
            }

        }
        public void stopSensor()
        {
            //sensorChooser.Stop();
            if (null == sensor)
            {
                return;
            }

            // Stop streaming
            sensor.Stop();

            if (null != sensor.AudioSource)
            {
                sensor.AudioSource.Stop();
            }

            if (null != sensor.SkeletonStream)
            {
                sensor.SkeletonStream.Disable();
            }

            if (null != sensor.DepthStream)
            {
                sensor.DepthStream.Disable();
            }

            if (null != sensor.ColorStream)
            {
                sensor.ColorStream.Disable();
            }

        }
        public void turnNull()
        {
            this.sensorChooser = null;
        }
        public void restart()
        {
            stopSensor();
            startSensor();
        }

        private static void SensorChooserOnKinectChanged(object sender, KinectChangedEventArgs args)
        {
            if (args.OldSensor != null)
            {
                try
                {
                    args.OldSensor.DepthStream.Range = DepthRange.Default;
                    args.OldSensor.SkeletonStream.EnableTrackingInNearRange = false;
                    args.OldSensor.DepthStream.Disable();
                    args.OldSensor.SkeletonStream.Disable();
                }
                catch (InvalidOperationException)
                {
                    // KinectSensor might enter an invalid state while enabling/disabling streams or stream features.
                    // E.g.: sensor might be abruptly unplugged.
                }
            }

            if (args.NewSensor != null)
            {
                try
                {
                    args.NewSensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
                    args.NewSensor.SkeletonStream.Enable();

                    try
                    {
                        args.NewSensor.DepthStream.Range = DepthRange.Near;
                        args.NewSensor.SkeletonStream.EnableTrackingInNearRange = true;
                    }
                    catch (InvalidOperationException)
                    {
                        // Non Kinect for Windows devices do not support Near mode, so reset back to default mode.
                        args.NewSensor.DepthStream.Range = DepthRange.Default;
                        args.NewSensor.SkeletonStream.EnableTrackingInNearRange = false;
                    }
                }
                catch (InvalidOperationException)
                {
                    // KinectSensor might enter an invalid state while enabling/disabling streams or stream features.
                    // E.g.: sensor might be abruptly unplugged.
                }
            }
        }

        public void findKinectSensor()
        {
            foreach (var potentialSensor in KinectSensor.KinectSensors)
            {
                if (potentialSensor.Status == KinectStatus.Connected)
                {
                    this.sensor = potentialSensor;
                    break;
                }
            }
        }

        public void enableSkeletonStream(EventHandler<SkeletonFrameReadyEventArgs> SensorSkeletonFrameReady)
        {
            if (null != this.sensor)
            {
                // Turn on the skeleton stream to receive skeleton frames
                this.sensor.SkeletonStream.Enable();

                // Add an event handler to be called whenever there is new color frame data
                this.sensor.SkeletonFrameReady += SensorSkeletonFrameReady;

                // Start the sensor!
                try
                {
                    this.sensor.Start();
                }
                catch (IOException)
                {
                    this.sensor = null;
                }
            }

            if (null == this.sensor)
            {
                //   this.messageTextBlock.Text = "kinect not ready";
            }
        }

        public Skeleton[] getSkeletons(SkeletonFrameReadyEventArgs e)
        {
            Skeleton[] skeletons = new Skeleton[0];

            using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
            {
                if (skeletonFrame != null)
                {
                    skeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
                    skeletonFrame.CopySkeletonDataTo(skeletons);
                }
            }
            return skeletons;
        }

       
    }
}
